﻿using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;

using BodaNetCommunications.Cores;
using BodaNetCommunications.FinsComs.FinsUtils;
using BodaNetCommunications.Utilities.ComTypes;
using BodaNetCommunications.Utilities.Results;

namespace BodaNetCommunications.FinsComs
{
    public class FinsTcp : ICommDevice
    {
        /// <summary>
        /// 根据数据类型，转换数据类型
        /// </summary>
        public EndianType EndianType { get; set; } = EndianType.AB;

        private ICommUnit _commUnit;

        public ConnectionOptions Options { get; private set; }

        public bool IsConnected => _commUnit != null && _commUnit.IsConnected;

        private int _pduSize = 500; // 指的是功能码以后的字节数，最大540

        private byte _sa1, _da1;

        public FinsTcp()
        {

        }

        public BodaResult Connect(ConnectionOptions connectionOptions)
        {
            BodaResult bodaResult = new BodaResult();
            Options = connectionOptions;

            if (string.IsNullOrEmpty(Options.Ip) || false == IPAddress.TryParse(Options.Ip, out _))
            {
                bodaResult.IsSuccess = false;
                bodaResult.Message = $"Ip[{Options.Ip}]为空或者格式不正确";
                return bodaResult;
            }

            if (Options.Port < 0 || Options.Port > 65535)
            {
                bodaResult.IsSuccess = false;
                bodaResult.Message = $"Port[{Options.Port}]不正确";
                return bodaResult;
            }

            if (IsConnected)
            {
                bodaResult.IsSuccess = true;
                bodaResult.Message = $"FinsTcp【{Options.Ip}:{Options.Port}】的连接已经在线，不需要重复连接";
                return bodaResult;
            }

            _commUnit = new CommUnitFins(Options.Ip.Trim(), Options.Port);

            // 连接分步
            BodaResult<bool> result = _commUnit.Open(Options.ConnectTimeout);
            if (!result.IsSuccess) return result;

            var resultConnect = FinsTcpConnect();
            if (!resultConnect.IsSuccess) return result;

            return resultConnect;
        }

        private BodaResult FinsTcpConnect()
        {
            byte ip = GetIpAddress();
            // 握手报文
            List<byte> bytes = new List<byte> {
                0x46, 0x49, 0x4E, 0x53,  // FINS  Ascii编码
                0x00,0x00,0x00,0x0C,   // 后续字节数
                0x00,0x00,0x00,0x00,   // Command:客户端（上位机）连接到服务端（PLC）
                0x00,0x00,0x00,0x00,   // 错误码：表示无错误
                0x00,0x00,0x00,ip    // 本机IP地址末位    动态获取本机地址：注意    网卡选择
            };
            BodaResult<byte> result = _commUnit.SendAndReceive(bytes);
            if (!result.IsSuccess) return new BodaResult { IsSuccess = false, Message = result.Message };

            // result.Datas  List<byte>
            byte errorCode = result.Datas[15];
            if (errorCode != 0x00)
            {
                return new BodaResult { IsSuccess = false, Message = FinsErrors.HeaderError[errorCode] };
            }

            _sa1 = result.Datas[19];
            _da1 = result.Datas[23];

            return new BodaResult() { IsSuccess = true, Message = result.Message }; ;
        }

        private byte GetIpAddress()
        {
            if (_commUnit == null || _commUnit.LocalEndPoint == null) return 0x00;

            IPAddress? ipa = (_commUnit.LocalEndPoint as IPEndPoint)?.Address;
            if (ipa == null) return 0x00;

            string ip = ipa.ToString(); //"192.168.151.1";
            string[] ips = ip.Split('.');
            return byte.Parse(ips[3]);
        }

        public void Disconnect()
        {
            _commUnit?.Close();
        }



        // 获取数据：指的获取多少个寄存器？还是多少个数据？
        // 一个数据需要两个寄存器   Float
        // count：指的是需要获取的数据个数
        /// <summary>
        /// 根据所提供的泛型类型，以及寄存器地址信息，获取指定类型的数据
        /// </summary>
        /// <typeparam name="T">需要获取的数据类型</typeparam>
        /// <param name="area">存储区类型</param>
        /// <param name="wordAddr">寄存器地址</param>
        /// <param name="bitAddr">位地址</param>
        /// <param name="count">需要获取的数据个数</param>
        /// <param name="dataTypeLength">数据类型的长度</param>
        /// <returns></returns>
        public BodaResult<T> Read<T>(FinsAreas area, ushort wordAddr, byte bitAddr, ushort count, int dataTypeLength = 0)
        {
            BodaResult<T> result = new BodaResult<T>();

            // bool类型长度为1
            int typeLen = 1;

            byte a = (byte)area;
            if (typeof(T) != typeof(bool))
            {
                a += 0x80;

                // 如果是short，则长度为2
                typeLen = dataTypeLength == 0 ? Marshal.SizeOf<T>() : dataTypeLength;
            }

            try
            {
                // Bool  一个数据一个Byte     count*1个字节
                // Word  一个数据两个Byte     count*2个字节
                // Float 一个数据四个Byte     count*4个字节
                int total = typeLen * count; // 整个请求的字节数
                ushort start = wordAddr;
                while (total > 0)
                {
                    // 字节数
                    ushort len = (ushort)Math.Min(total, _pduSize);

                    List<byte> bytes = new List<byte> {
                        // FinsTcp Header
                        0x46, 0x49, 0x4E, 0x53,  // FINS  Ascii编码
                        0x00,0x00,0x00,0x1A,   // 后续字节数
                        0x00,0x00,0x00,0x02,   // Command:客户端（上位机）连接到服务端（PLC）
                        0x00,0x00,0x00,0x00,   // 错误码：表示无错误
                        // Fins Header
                        0x80,
                        0x00,
                        0x02,
                        0x00,_da1,0x00,
                        0x00,_sa1,0x00,
                        0xFF,  // SID

                        // Command
                        0x01,0x01,
                        a, // 表示操作DM区的Word类型
                        (byte)(start/256%256),
                        (byte)(start%256), // Word地址
                        bitAddr, // 位地址
                        (byte)(len/2/256%256),
                        (byte)(len/2%256)  // 读取个数
                    };

                    BodaResult<byte> respRersult = _commUnit.SendAndReceive(bytes);
                    if (!respRersult.IsSuccess)
                    {
                        result.IsSuccess = false;
                        result.Message = respRersult.Message;
                        return result;
                    }

                    // 检查Header Error Code
                    byte errorCode = respRersult.Datas[15];
                    if (errorCode != 0x00)
                    {
                        result.IsSuccess = false;
                        result.Message = FinsErrors.HeaderError[errorCode];
                        return result;
                    }

                    // 检查 Command Error Code
                    // 
                    List<byte> cec = respRersult.Datas.GetRange(28, 2);
                    if (cec.Sum(b => b) > 0)
                    {
                        result.IsSuccess = false;
                        result.Message = FinsErrors.GetCommandError(cec[0], cec[1]);
                        return result;
                    }


                    // 数据解析
                    // 从数据字节开始，获取剩余长度的响应字节
                    respRersult.Datas.RemoveRange(0, 30);

                    for (int i = 0; i < respRersult.Datas.Count;)
                    {
                        if (typeof(T) == typeof(bool))
                        {
                            dynamic boolValue = respRersult.Datas[i] == 0x01;
                            result.Datas.Add(boolValue);
                            i++;
                        }
                        else
                        {
                            // 不考虑Byte类型的数据  Word  DWord
                            List<byte> dataBytes = respRersult.Datas.GetRange(i, typeLen);
                            //dataBytes.Reverse();
                            dataBytes = this.SwitchEndianType(dataBytes);

                            if (typeof(T) == typeof(byte))
                            {
                                result.Datas.AddRange((IEnumerable<T>)dataBytes);
                            }
                            else
                            {
                                // 转换数据 
                                Type tBitConverter = typeof(BitConverter);
                                MethodInfo? method = tBitConverter.GetMethods(BindingFlags.Public | BindingFlags.Static)
                                    .FirstOrDefault(mi => mi.ReturnType == typeof(T)
                                    && mi.GetParameters().Length == 2) as MethodInfo;
                                if (method == null)
                                {
                                    result.IsSuccess = false;
                                    result.Message = "未找到匹配的数据类型转换方法";
                                    return result;
                                }

                                result.Datas.Add((T)method?.Invoke(tBitConverter, new object[] { dataBytes.ToArray(), 0 })!);

                            }

                            i += typeLen;
                        }
                    }

                    total -= len;
                    if (typeof(T) == typeof(bool))
                        start += (ushort)(len / 16);
                    else
                        start += (ushort)(len / 2);

                }//while end

            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
                return result;
            }

            return result;
        }

        // CIO0.1    0.1
        // D0   D0.1
        // W0   W0.1
        public BodaResult<T> Read<T>(string variable, ushort count)
        {
            try
            {
                var (area, wa, ba) = this.AnalysisAddress(variable);

                var dataTypeLength = 0;

                // 如果是字节
                if (typeof(T) == typeof(byte))
                {
                    switch (area)
                    {
                        case FinsAreas.CIO:
                            break;
                        case FinsAreas.WR:
                            break;
                        case FinsAreas.HR:
                            break;
                        case FinsAreas.AR:
                            break;
                        case FinsAreas.DM:
                            dataTypeLength = 2;
                            break;
                        default:
                            break;
                    }
                }

                return this.Read<T>(area, wa, ba, count, dataTypeLength);
            }
            catch (Exception ex)
            {
                return new BodaResult<T>() { IsSuccess = false, Message = ex.Message };
            }
        }

        public BodaResult Write<T>(FinsAreas area, ushort wordAddr, byte bitAddr, List<T> datas)
        {
            BodaResult result = new BodaResult();

            int typeLen = 1;
            ushort dataLen = (ushort)(datas.Count);  // 默认   有多少个就是多少个    Bool

            byte a = (byte)area;
            if (typeof(T) != typeof(bool))
            {
                a += 0x80;
                typeLen = Marshal.SizeOf<T>();

                dataLen = (ushort)(datas.Count * typeLen / 2);
            }
            // Word  不需要 /2   Float   需要 /2

            try
            {
                // 分组处理   自行解决
                List<byte> commandBytes = new List<byte>() { 0x46, 0x49, 0x4E, 0x53 };

                List<byte> bytes = new List<byte> {
                    0x00,0x00,0x00,0x02,   // Command:客户端（上位机）连接到服务端（PLC）
                    0x00,0x00,0x00,0x00,   // 错误码：表示无错误
                    // Fins Header
                    0x80,
                    0x00,
                    0x02,
                    0x00,_da1,0x00,
                    0x00,_sa1,0x00,
                    0xFF,  // SID

                    // Command
                    0x01,0x02,
                    a, // 表示操作DM区的Word类型
                    (byte)(wordAddr / 256 % 256),
                    (byte)(wordAddr % 256), // Word地址   
                    bitAddr, // 位地址

                    (byte)(dataLen / 256 % 256),
                    (byte)(dataLen % 256),  // 写入个数

                    //// 需要写入的数据
                    //0x00,0x0B, // Word  ->  2 Bytes
                    //0x00,0x0C,
                    //0x00,0x0D
                };
                datas.ForEach(d =>
                {
                    if (typeof(T) == typeof(bool))
                    {
                        bytes.Add((byte)(bool.Parse(d.ToString()) ? 0x01 : 0x00));
                    }
                    else
                    {
                        // 获取每个数据的字节数组
                        dynamic data = d;
                        List<byte> vBytes = new List<byte>(BitConverter.GetBytes(data));    // 123     ->  00 7B     7B 00
                        // 调整字节顺序
                        vBytes = this.SwitchEndianType(vBytes);
                        // 将数据字节添加到报文后面
                        bytes.AddRange(vBytes);
                    }
                });

                commandBytes.Add((byte)(bytes.Count / 256 / 256 / 256 % 256));
                commandBytes.Add((byte)(bytes.Count / 256 / 256 % 256));
                commandBytes.Add((byte)(bytes.Count / 256 % 256));
                commandBytes.Add((byte)(bytes.Count % 256));

                commandBytes.AddRange(bytes);


                BodaResult<byte> respRersult = _commUnit.SendAndReceive(commandBytes);
                if (!respRersult.IsSuccess)
                {
                    result.IsSuccess = false;
                    result.Message = respRersult.Message;
                    return result;
                }

                // 检查Header Error Code
                byte errorCode = respRersult.Datas[15];
                if (errorCode != 0x00)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.HeaderError[errorCode];
                    return result;
                }

                // 检查 Command Error Code
                // 
                List<byte> cec = respRersult.Datas.GetRange(28, 2);
                if (cec.Sum(b => b) > 0)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.GetCommandError(cec[0], cec[1]);
                    return result;
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }

            return result;
        }

        public BodaResult Write<T>(string variable, List<T> datas)
        {
            try
            {
                var (area, wa, ba) = this.AnalysisAddress(variable);

                return this.Write<T>(area, wa, ba, datas);
            }
            catch (Exception ex)
            {
                return new BodaResult() { IsSuccess = false, Message = ex.Message };
            }
        }


        // T:Bool  /  ushort  short  uint16  int16     float   double   long   int
        // Fill 针对的是存储地址，  一个地址最大    Word
        public BodaResult Fill<T>(FinsAreas area, ushort wordAddr, byte bitAddr, ushort count, T data) where T : IComparable
        {
            BodaResult result = new BodaResult();

            byte a = (byte)area;
            byte len = 0x1B;
            if (typeof(T) != typeof(bool))
            {
                a += 0x80;
                len = 0x1C;
            }

            try
            {
                List<byte> bytes = new List<byte> {
                    // FinsTcp Header
                    0x46, 0x49, 0x4E, 0x53,  // FINS  Ascii编码
                    0x00,0x00,0x00,len,   // 后续字节数
                    0x00,0x00,0x00,0x02,   // Command:客户端（上位机）连接到服务端（PLC）
                    0x00,0x00,0x00,0x00,   // 错误码：表示无错误
                    // Fins Header
                    0x80,
                    0x00,
                    0x02,
                    0x00,_da1,0x00,
                    0x00,_sa1,0x00,
                    0xFF,  // SID

                    // Command
                    0x01,0x03,
                    a, // 表示操作DM区的Word类型
                    (byte)(wordAddr / 256 % 256),
                    (byte)(wordAddr % 256), // Word地址   
                    bitAddr, // 位地址

                    (byte)(count / 256 % 256),
                    (byte)(count % 256),  // 写入个数
                    // 需要填充的数据
                    0x00,0x01   // 填充Bit   0x00/0x01       Word  0x00 0x01
                    // 
                };
                if (typeof(T) == typeof(bool))
                    bytes.Add((byte)(bool.Parse(data.ToString()) ? 0x01 : 0x00));
                else
                {
                    ushort d = (ushort)Convert.ChangeType(data, typeof(ushort));
                    List<byte> vbytes = new List<byte>(BitConverter.GetBytes(d));

                    vbytes = this.SwitchEndianType(vbytes);
                    bytes.AddRange(vbytes);
                }

                BodaResult<byte> respRersult = _commUnit.SendAndReceive(bytes);
                if (!respRersult.IsSuccess) throw new Exception(respRersult.Message);

                // 检查Header Error Code
                byte errorCode = respRersult.Datas[15];
                if (errorCode != 0x00)
                    throw new Exception(FinsErrors.HeaderError[errorCode]);

                // 检查 Command Error Code
                // 
                List<byte> cec = respRersult.Datas.GetRange(28, 2);
                if (cec.Sum(b => b) > 0)
                {
                    throw new Exception(FinsErrors.GetCommandError(cec[0], cec[1]));
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }
            // 为什么没有finally ？什么情况下使用finally

            return result;
        }


        // 使用元组返回多个结果，C#7.0语法 
        private (FinsAreas, ushort, byte) AnalysisAddress(string variable)
        {
            FinsAreas area = FinsAreas.CIO;
            ushort wordAddr = 0;
            byte bitAddr = 0;

            string[] addr = new string[1];


            variable = variable.ToUpperInvariant();
            if (variable.Substring(0, 2) == "CI")
            {
                addr = variable.Remove(0, 3).Split('.');
            }
            else
            {
                char f = variable[0];
                if (f == 'D')
                    area = FinsAreas.DM;
                else if (f == 'W')
                    area = FinsAreas.WR;

                addr = variable.Remove(0, 1).Split('.');
            }

            // 判断是否能够转换
            wordAddr = ushort.Parse(addr[0]);
            if (addr.Length > 1)
                bitAddr = byte.Parse(addr[1]);

            return (area, wordAddr, bitAddr);
        }



        /// <summary>
        /// 表示将一个数据字节进行指定字节序的调整
        /// </summary>
        /// <param name="bytes">接收待转换的设备中返回的字节数组</param>
        /// <returns>返回调整完成的字节数组</returns>
        private List<byte> SwitchEndianType(List<byte> bytes)
        {
            // 不管是什么字节序，这个Switch里返回的是ABCD这个顺序
            List<byte> temp = new List<byte>();
            switch (EndianType)  // alt+enter
            {
                case EndianType.AB:
                case EndianType.ABCD:
                case EndianType.ABCDEFGH:
                    temp = bytes;
                    break;
                case EndianType.BA:
                case EndianType.DCBA:
                case EndianType.HGFEDCBA:
                    for (int i = bytes.Count - 1; i >= 0; i--)
                        temp.Add(bytes[i]);
                    break;
                case EndianType.CDAB:
                    temp = new List<byte> { bytes[2], bytes[3], bytes[0], bytes[1] };
                    break;
                case EndianType.BADC:
                    temp = new List<byte> { bytes[1], bytes[0], bytes[3], bytes[2] };
                    break;
                case EndianType.GHEFCDAB:
                    temp = new List<byte> { bytes[6], bytes[7], bytes[4], bytes[5], bytes[2], bytes[3], bytes[0], bytes[1] };
                    break;
                case EndianType.BADCFEHG:
                    break;
            }

            if (BitConverter.IsLittleEndian)
                temp.Reverse();

            return temp;
        }



        public BodaResult<DateTime> GetTime()
        {
            BodaResult<DateTime> result = new BodaResult<DateTime>();

            try
            {
                List<byte> bytes = new List<byte> {
                    // FinsTcp Header
                    0x46, 0x49, 0x4E, 0x53,  // FINS  Ascii编码
                    0x00,0x00,0x00,0x14,   // 后续字节数
                    0x00,0x00,0x00,0x02,   // Command:客户端（上位机）连接到服务端（PLC）
                    0x00,0x00,0x00,0x00,   // 错误码：表示无错误
                    // Fins Header
                    0x80,
                    0x00,
                    0x02,
                    0x00,_da1,0x00,
                    0x00,_sa1,0x00,
                    0xFF,  // SID

                    // Command
                    0x07,0x01  // 表示读取PLC时间
                };

                BodaResult<byte> respResult = _commUnit.SendAndReceive(bytes);
                if (!respResult.IsSuccess)
                {
                    result.IsSuccess = false;
                    result.Message = respResult.Message;
                    return result;
                }

                // 检查Header Error Code
                byte errorCode = respResult.Datas[15];
                if (errorCode != 0x00)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.HeaderError[errorCode];
                    return result;
                }

                // 检查 Command Error Code
                // 
                List<byte> cec = respResult.Datas.GetRange(28, 2);
                if (cec.Sum(b => b) > 0)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.GetCommandError(cec[0], cec[1]);
                    return result;
                }

                int year = 2000 + int.Parse(respResult.Datas[30].ToString("X2"));   // 0x22
                int month = int.Parse(respResult.Datas[31].ToString("X2"));
                int day = int.Parse(respResult.Datas[32].ToString("X2"));
                int hour = int.Parse(respResult.Datas[33].ToString("X2"));
                int minute = int.Parse(respResult.Datas[34].ToString("X2"));
                int second = int.Parse(respResult.Datas[35].ToString("X2"));

                result.Datas.Add(new DateTime(year, month, day, hour, minute, second));
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }
            return result;
        }

        public BodaResult SetTime(DateTime dt)
        {
            BodaResult result = new BodaResult();

            string yearStr = dt.Year.ToString();
            byte year = Convert.FromHexString(yearStr)[1];
            byte month = Convert.FromHexString(dt.Month.ToString("00"))[0];
            byte day = Convert.FromHexString(dt.Day.ToString("00"))[0];
            byte hour = Convert.FromHexString(dt.Hour.ToString("00"))[0];
            byte minute = Convert.FromHexString(dt.Minute.ToString("00"))[0];
            byte second = Convert.FromHexString(dt.Second.ToString("00"))[0];
            byte week = Convert.FromHexString(dt.DayOfWeek.ToString("00"))[0];

            try
            {
                List<byte> bytes = new List<byte> {
                    // FinsTcp Header
                    0x46, 0x49, 0x4E, 0x53,  // FINS  Ascii编码
                    0x00,0x00,0x00,0x1B,   // 后续字节数
                    0x00,0x00,0x00,0x02,   // Command:客户端（上位机）连接到服务端（PLC）
                    0x00,0x00,0x00,0x00,   // 错误码：表示无错误
                    // Fins Header
                    0x80,
                    0x00,
                    0x02,
                    0x00,_da1,0x00,
                    0x00,_sa1,0x00,
                    0xFF,  // SID

                    // Command
                    0x07,0x02,  // 表示读取PLC时间
                    // 年、月、日、时、分、秒  星期
                    year,month,day,hour,minute,second,week
                };

                BodaResult<byte> respResult = _commUnit.SendAndReceive(bytes);
                if (!respResult.IsSuccess)
                {
                    result.IsSuccess = false;
                    result.Message = respResult.Message;
                    return result;
                }

                // 检查Header Error Code
                byte errorCode = respResult.Datas[15];
                if (errorCode != 0x00)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.HeaderError[errorCode];
                    return result;
                }

                // 检查 Command Error Code
                // 
                List<byte> cec = respResult.Datas.GetRange(28, 2);
                if (cec.Sum(b => b) > 0)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.GetCommandError(cec[0], cec[1]);
                    return result;
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }
            return result;
        }

        public BodaResult Run(RunModeType runMode = RunModeType.RUN)
        {
            BodaResult result = new BodaResult();

            try
            {
                List<byte> bytes = new List<byte> {
                    // FinsTcp Header
                    0x46, 0x49, 0x4E, 0x53,
                    0x00,0x00,0x00,0x17,
                    0x00,0x00,0x00,0x02,
                    0x00,0x00,0x00,0x00,   
                    // Fins Header
                    0x80,
                    0x00,
                    0x02,
                    0x00,_da1,0x00,
                    0x00,_sa1,0x00,
                    0xFF,  // SID

                    // Command
                    0x04,0x01,

                    0xFF,0xFF,  // 固定值  Program No.
                    (byte)runMode        // 04 运行模式   01  Debug    02  Monitor
                };

                BodaResult<byte> respResult = _commUnit.SendAndReceive(bytes);
                if (!respResult.IsSuccess)
                {
                    result.IsSuccess = false;
                    result.Message = respResult.Message;
                    return result;
                }

                // 检查Header Error Code
                byte errorCode = respResult.Datas[15];
                if (errorCode != 0x00)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.HeaderError[errorCode];
                    return result;
                }

                // 检查 Command Error Code
                // 
                List<byte> cec = respResult.Datas.GetRange(28, 2);
                if (cec.Sum(b => b) > 0)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.GetCommandError(cec[0], cec[1]);
                    return result;
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }
            return result;
        }


        public BodaResult Stop()
        {
            BodaResult result = new BodaResult();

            try
            {
                List<byte> bytes = new List<byte> {
                    // FinsTcp Header
                    0x46, 0x49, 0x4E, 0x53,
                    0x00,0x00,0x00,0x14,
                    0x00,0x00,0x00,0x02,
                    0x00,0x00,0x00,0x00,   
                    // Fins Header
                    0x80,
                    0x00,
                    0x02,
                    0x00,_da1,0x00,
                    0x00,_sa1,0x00,
                    0xFF,  // SID

                    // Command
                    0x04,0x02
                };

                BodaResult<byte> respResult = _commUnit.SendAndReceive(bytes);
                if (!respResult.IsSuccess)
                {
                    result.IsSuccess = false;
                    result.Message = respResult.Message;
                    return result;
                }

                // 检查Header Error Code
                byte errorCode = respResult.Datas[15];
                if (errorCode != 0x00)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.HeaderError[errorCode];
                    return result;
                }

                List<byte> cec = respResult.Datas.GetRange(28, 2);
                if (cec.Sum(b => b) > 0)
                {
                    result.IsSuccess = false;
                    result.Message = FinsErrors.GetCommandError(cec[0], cec[1]);
                    return result;
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = ex.Message;
            }
            return result;
        }

        public BodaResult SendMsgc(byte[] bytes, int timeout = 1500)
        {
            throw new NotImplementedException();
        }

        public BodaResult<byte> ReceiveMsg(int timeout = 2000, int bytesLen = 1024)
        {
            throw new NotImplementedException();
        }
    }
}
